package br.biofoco.p2p.peer;

import java.io.IOException;
import java.util.Collection;
import java.util.Map;

import br.biofoco.p2p.dht.AbstractDHT;
import br.biofoco.p2p.dht.DHTService;
import br.biofoco.p2p.dht.SeedProvider;
import br.biofoco.p2p.rpc.EndPoint;
import br.biofoco.p2p.rpc.Protocol;
import br.biofoco.p2p.rpc.TransportManager;
import br.biofoco.p2p.rpc.service.Messenger;

import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Maps;


public class PeerNodeImpl implements PeerNode {

	private ID id;	
	private Map<Protocol,EndPoint> endpoints = Maps.newEnumMap(Protocol.class);
	private final PeerConfig config;
	private final TransportManager manager;
	private final Messenger messenger;
	private AbstractDHT dht;

	public PeerNodeImpl(PeerConfig config, TransportManager manager, DhtFactory dhtFactory) {
		
		this.config = config;
		this.id = config.getPeerID();
		
		for (EndPoint e : config.getEndPoints()) {
			endpoints.put(e.getProtocol(), e);
			manager.registerTransport(e);			
		}
		
		this.manager = manager;
		messenger = new Messenger(manager);
		
		dht = dhtFactory.get(this);
	}
	
	public Messenger getMessenger() {
		return messenger;
	}

	@Override
	public ID getPeerID() {
		return id;
	}

	@Override
	public Collection<EndPoint> getEndPoints() {
		return ImmutableSet.copyOf(endpoints.values());
	}
	
	public void start() throws IOException {
		manager.startAll();
		dht.start();
	}
	
	public void stop() throws IOException {
		manager.stopAll();
		dht.stop();
	}
		
	@Override
	public String toString() {
		return id + ":" + endpoints;
	}

	@Override
	public PeerConfig getPeerConfig() {
		return config;
	}

	@Override
	public EndPoint getEndPoint(Protocol proto) {
		return endpoints.get(proto);
	}

	@Override
	public Collection<PeerNode> getPeerView() {
		return dht.getPeerView();
	}
	
	@Override
	public int hashCode() {
		return id.hashCode();
	}
	
	@Override
	public boolean equals(Object object) {
		if (this == object)
			return true;
		if (!(object instanceof PeerNode)){
			return false;
		}
		
		PeerNode other = (PeerNode) object;
		
		return this.getPeerID().equals(other.getPeerID());
	}
	

}